﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using AvansRS.Domain;
using AvansRS.Domain.DataInterface;
using NHibernate;
using System.Collections.ObjectModel;
using NHibernate.Criterion;
using NHibernate.Exceptions;

namespace AvansRS.Data
{
    public class BaseRepository<T> : IRepository<T>
    {
        private void Validate(T domainObject)
        {
            ValidationContext context = new ValidationContext(domainObject, null, null);
            Validator.ValidateObject(domainObject, context);
        }

		  public virtual void SaveWithoutValidate(T domainObject)
		  {
			  try
			  {
				  using(ISession session = SessionProvider.GetSession())
				  {
					  session.Update(domainObject);
					  session.Flush();
				  }
			  }
			  catch(GenericADOException ex)
			  {
				  throw new DataException(ex.Message, ex);
			  }
		  }

		  public virtual void AddWithoutValidate(T domainObject)
		  {
			  try
			  {
				  using(ISession session = SessionProvider.GetSession())
				  {
					  session.Save(domainObject);
					  session.Flush();
				  }
			  }
			  catch(GenericADOException ex)
			  {
				  throw new DataException(ex.Message, ex);
			  }
		  }

        public virtual void Add(T domainObject)
        {
            Validate(domainObject);
            try
            {
                using (ISession session = SessionProvider.GetSession())
                {
                    session.Save(domainObject);
                    session.Flush();
                }
            }
            catch(GenericADOException ex)
            {
                throw new DataException(ex.Message, ex);
            }
        }

        public void Delete(T domainObject)
        {
            try
            {
                using (ISession session = SessionProvider.GetSession())
                {
                    session.Delete(domainObject);
                    session.Flush();
                }
            }
            catch (GenericADOException ex)
            {
                throw new DataException(ex.Message, ex);
            }
        }

        public void Save(T domainObject)
        {
            Validate(domainObject);
            
            try
            {
                using (ISession session = SessionProvider.GetSession())
                {
                    session.Update(domainObject);
                    session.Flush();
                }
            }
            catch (GenericADOException ex)
            {
                throw new DataException(ex.Message, ex);
            }
        }

        public IList<T> GetAll()
        {
            try
            {
                using (ISession session = SessionProvider.GetSession())
                {
                    IList<T> list = session.CreateCriteria(typeof(T))
                        .List<T>();
                    return list;
                }
            }
            catch (GenericADOException ex)
            {
                throw new DataException(ex.Message, ex);
            }
        }

        public T GetByID(int ID)
        {
            try
            {
                using (ISession session = SessionProvider.GetSession())
                {
                    T domainObject = session.CreateCriteria(typeof(T))
                       .Add(Expression.Eq("ID", ID))
                       .UniqueResult<T>();

                    return domainObject;
                }
            }
            catch (GenericADOException ex)
            {
                throw new DataException(ex.Message, ex);
            }
        }
    }
}